package com.mew.chess.core.common.handler;


import com.mew.chess.core.common.message.request.EnterGameRequestMessage;
import com.mew.chess.core.common.message.request.ReconnectionGameRequestMessage;
import com.mew.common.dc.redis.AucRedisService;
import com.mew.common.exception.ResponseCode;
import com.mew.common.rest.bo.GameSession;
import com.mew.common.rest.bo.MewSession;
import com.zebra.common.GoldPushMessage;
import com.zebra.common.ZebraException;
import com.zebra.remoting.config.BasisCommandCode;
import com.zebra.remoting.config.StateCode;
import com.zebra.remoting.connection.Connection;
import com.zebra.remoting.protocol.ZebraCommand;
import com.zebra.remoting.tms.AbstractServerHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;


@Component
@Slf4j
public class ChannelHandlerService extends AbstractServerHandler {

    @Autowired
    private AucRedisService aucRedisService;
    @Autowired
    private ChessSessionManager chessSessionManager;
    @Autowired
    private EnterExitRoomService enterExitRoomService;

    @Override
    public void doHandler(ZebraCommand command) throws Exception {
        MewSession session = aucRedisService.getSession(command.getUserId());
        GameSession chessSession = chessSessionManager.get(command.getUserId());

        if (BasisCommandCode.OFFLINE.cmd() == command.getCmd()){
            log.info("Handler offline: {} {}  {}", command,
                    null == session ? "session is null" : session.toString(),
                    null == chessSession ? "gameSession is null" : chessSession.toString());
            enterExitRoomService.offlineByGw(command, session, chessSession);
            return;
        }

        if (BasisCommandCode.GOLDPUSH.cmd() == command.getCmd()){
            log.info("Handler GOLDPUSH:  current gold: {} {}", chessSession == null ? "gameSession is null" : chessSession.getGoldNumber(), command);
            if (chessSession != null){
                GoldPushMessage goldPushMessage = (GoldPushMessage) command.getRequest();
                chessSession.updateGoldNumber(goldPushMessage.getGoldNumber());
            }
            return;
        }


        //switch channel by same server
        if (BasisCommandCode.SWITCHTMS.cmd() == command.getCmd()){
            if (session == null){
                log.error("Handler SWITCHTMS MewSession is null {}", command);
                return;
            }
            if (null == chessSession){
                log.error("Handler SWITCHTMS ChessSession is null {}", command);
                return;
            }
            log.info("Handler SWITCHTMS {}", command);
            chessSession.setChannel(command.getChannel());
            return;
        }

        //-----校验-------------
        if (command.getCommandModel().isVerifyType()) {
            if (null == session || session.tk != command.getToken()){
                command.sendFailureCode(StateCode.LoginUn.code());
                log.error("Handler offline: session failure   {} ses:{}", command, null == session ? "" : session.toString());
                enterExitRoomService.offline(chessSession);
                return;
            }
        }

        ChessHandlerMapCmdType cmdType = ChessHandlerMapCmdType.valueOfCode(command.getCmd());
        if (null == cmdType){
            cmdInvalid(command, chessSession);
            return;
        }

        if (cmdType != ChessHandlerMapCmdType.EnterRoom && cmdType != ChessHandlerMapCmdType.ReconnectRoom){
            if (chessSession == null || session.tk != chessSession.getTk()){
                log.error("Handler GameSession and MewSession  failure; {} {}", session.toString(), chessSession == null ? "" : chessSession.toString());
                cmdInvalid(command, chessSession);
                return;
            }
        }

        switch (cmdType){
            case EnterRoom: {
                doEnterRoom(command, session, chessSession);
                break;
            }

            case ReconnectRoom: {
                doReconnectRoom(command, session, chessSession);
                break;
            }

            case ExitRoom: {
                doExitRoom(command, session,  chessSession);
                break;
            }

            default: {
                doDefault(command, chessSession);
                break;
            }

        }
    }

    private void doEnterRoom(ZebraCommand<EnterGameRequestMessage> command, MewSession session, GameSession chessSession) throws ZebraException {
        String vfx = GameInfoMananger.getInstance().get(command.getGameId()).getGameVfx();
        ChessEEHandler chessEEHandler = getChessEEHandler(vfx, command);
        if (null == chessEEHandler){
            return;
        }
        chessEEHandler.enterRoom(command, session, chessSession);
    }


    private void doReconnectRoom(ZebraCommand<ReconnectionGameRequestMessage> command, MewSession session, GameSession chessSession)throws ZebraException {
        String vfx = GameInfoMananger.getInstance().get(command.getGameId()).getGameVfx();
        ChessEEHandler chessEEHandler = getChessEEHandler(vfx, command);
        if (null == chessEEHandler){
            return;
        }
        chessEEHandler.reconnectRoom(command, session, chessSession);
    }

    private void doExitRoom(ZebraCommand command, MewSession session, GameSession chessSession)throws ZebraException {
        ChessEEHandler chessEEHandler = getChessEEHandler(chessSession.getVfx(), command);
        if (null == chessEEHandler){
            return;
        }
        chessEEHandler.exit(command, session, chessSession);
    }

    private ChessEEHandler getChessEEHandler(String vfx, ZebraCommand command) throws ZebraException {
        ChessEEHandler chessEEHandler = InitializeEEHandlerMapping.getMapping(vfx);
        if (null == chessEEHandler){
            log.error("Handler ChessEEHandler is null: vfx {} {}", vfx, command.toString());
            command.sendFailureCode(ResponseCode.GameServerDowntime.code());
            return null;
        }
        return chessEEHandler;
    }

    private void doDefault(ZebraCommand command, GameSession session) throws ZebraException {
        ChessPlayHandler chessPlayHandler = InitializePlayHandlerMapping.getMapping(command.getCmd());
        if (null == chessPlayHandler){
            log.error("Handler ChessPlayHandler is null {}", command.toString());
            cmdInvalid(command, session);
            return;
        }
        chessPlayHandler.handle(command, session);
    }


    @Override
    public void doChannelInactive(Connection connection) throws Exception {
        List<GameSession> list = chessSessionManager.findByChannel(connection.getChannel());
        if (null == list || list.isEmpty()){
            return;
        }
        log.error("Handler Gateway inactive: {}", connection.toString());
        list.stream().forEach(cs -> {
            log.error("Handler Gateway inactive session: {}  ", cs.toString());
            enterExitRoomService.offline(cs);
        });
    }

    @Override
    public void doTmsOffline() {
        log.info("------------RA-to-TMS-Offline--1 M-exe---user-offline---------------");
    }


    private void  cmdInvalid(ZebraCommand command, GameSession chessSession){
        log.error("Handler <-> CMD not mapping LoginUn {} ", command.toString());
        command.sendFailureCode(ResponseCode.LoginUn.code());
        enterExitRoomService.offline(chessSession);
    }


}



